package frsf.cidisi.exercise.laberinto.situationCalculus;

import frsf.cidisi.exercise.laberinto.situationCalculus.util.Celda;
import frsf.cidisi.exercise.laberinto.situationCalculus.util.Entorno;
import frsf.cidisi.exercise.laberinto.situationCalculus.util.Orientacion;
import frsf.cidisi.exercise.laberinto.situationCalculus.util.Par;
import frsf.cidisi.faia.state.EnvironmentState;

public class EstadoLaberinto extends EnvironmentState {
	
    private Par posicion;
    private Par posPrevia;
    private Orientacion orientacion;
    private boolean tieneLlave;
    private Entorno entorno;
    private String[][] laberinto;
        	
    public EstadoLaberinto() {
        
    }	
    
    public EstadoLaberinto(int filas, int columnas) {
        
    	this.entorno = new Entorno(filas, columnas);
		this.initState();
    }
    
    @Override
    public void initState() {
    	
    	tieneLlave = false;
    	orientacion = new Orientacion();
        posicion = null;
        posPrevia = null;
        laberinto = null;
    }

	//TODO: Complete this section with agent-specific methods
    // The following methods are agent-specific:

	public Par getPosicion() {
		return posicion;
	}

	public void setPosicion(Par posicion) {
		this.posPrevia = this.posicion;
		this.posicion = posicion;
	}

	public Orientacion getOrientacion() {
		return orientacion;
	}
	
	public void setOrientacion(Orientacion o) {
		this.orientacion = o;
	}

	public boolean isTieneLlave() {
		return tieneLlave;
	}

	public void setTieneLlave(boolean tieneLlave) {
		this.tieneLlave = tieneLlave;
	}
	
	public Entorno getEntorno() {
		return entorno;
	}

	public void setEntorno(Entorno entorno) {
		this.entorno = entorno;
	}
	
    @Override
    public String toString() {
//        String str = "";
	    
//	    str += "Posicion: " + this.getPosicion().toString();
//	    str += "; Orientacion: " + this.getOrientacion().toString();
	    
	    if (laberinto == null)
	    	inicializar();

		actualizar();
		
        return dibujar();
    }
    
    private void actualizar() {
	    if(this.posPrevia != null) {
	    	int x = this.posPrevia.getX() * 2 + 1;
			int y = this.posPrevia.getY() * 2 + 1;
			laberinto[x][y] = " ";
	    }
	    
	    if(!tieneLlave)
			for(Par llave : entorno.getLlaves()) {
				int x = llave.getX() * 2 + 1;
				int y = llave.getY() * 2 + 1;
				laberinto[x][y] = "L";
			}
		
		for(Par entrada : entorno.getEntradas()) {
			int x = entrada.getX() * 2 + 1;
			int y = entrada.getY() * 2 + 1;
			laberinto[x][y] = "E";
		}
		
		for(Par salida : entorno.getSalidas()) {
			int x = salida.getX() * 2 + 1;
			int y = salida.getY() * 2 + 1;
			laberinto[x][y] = "S";
		}
		
		for(Par cerrojo : entorno.getCerrojos()) {
			int x = cerrojo.getX() * 2 + 1;
			int y = cerrojo.getY() * 2 + 1;
			laberinto[x][y] = "C";
		}
	    
		int x = this.posicion.getX() * 2 + 1;
		int y = this.posicion.getY() * 2 + 1;
		
		switch(this.getOrientacion().getDireccion()) {
			case 0: laberinto[x][y] = "^"; break;
			case 1: laberinto[x][y] = ">"; break;
			case 2: laberinto[x][y] = "v"; break;
			case 3: laberinto[x][y] = "<"; break;
		}
		
		
	}

	private String dibujar() {
    	String out = "\n";
		for(int i = 0; i < laberinto.length; i++) {
			for(int j = 0; j < laberinto.length; j++)
				out += laberinto[i][j] + " ";
			out += "\n";
		}
		return out;
	}
	
	private  void inicializar() {
		Celda[][] lab = this.entorno.getLaberinto();
		
		int t = lab.length;
		int tam = t * 2 + 1;
		laberinto = new String[tam][tam];
		
		for(int i = 0; i < tam; i++)
			for(int j = 0; j < tam; j++)
				laberinto[i][j] = i % 2 == 0 && j % 2 == 0 ? "X" : " ";
		
		for(int i = 0; i < t; i++)
			for(int j = 0; j < t; j++) {
				Celda c = lab[i][j];
				int x = i * 2 + 1;
				int y = j * 2 + 1;
				laberinto[x - 1][y] = c.getEstado(Celda.getNorte()) == 0 ? "X": " ";
				laberinto[x][y + 1] = c.getEstado(Celda.getEste()) == 0 ? "X": " ";
				laberinto[x + 1][y] = c.getEstado(Celda.getSur()) == 0 ? "X": " ";
				laberinto[x][y - 1] = c.getEstado(Celda.getOeste()) == 0 ? "X": " ";
			}		
	}
}
